#include "../GeneralLibrary/Linkage.h"

.balign	 0x1000     // 指示程序计数器按4KB边界对齐

.text
.code16             // 指示编译器下面的代码是运行在实模式下的

ENTRY(APUBootStart)

APUBootBase = .
        cli
    	wbinvd

    	mov	%cs,	%ax
    	mov	%ax,	%ds
    	mov	%ax,	%es
    	mov	%ax,	%ss
    	mov	%ax,	%fs
    	mov	%ax,	%gs

    #	set sp

    	movl	$(APUBootTmpStackEnd - APUBootBase),	%esp

    #	get base address

    	mov	%cs,	%ax
    	movzx	%ax,	%esi
    	shll	$4,	%esi

    #	set gdt and 32&64 code address

    	leal	(APUCode32 - APUBootBase)(%esi),	%eax
    	movl	%eax,	APUCode32Vector - APUBootBase

    	leal	(APUCode64 - APUBootBase)(%esi),	%eax
    	movl	%eax,	APUCode64Vector - APUBootBase

    	leal	(APUTmpGDT - APUBootBase)(%esi),	%eax
    	movl	%eax,	(APUTmpGDT + 2 - APUBootBase)

    #	load idt gdt

    	lidtl	APUTmpIDT - APUBootBase
    	lgdtl	APUTmpGDT - APUBootBase

    #	enable protected mode

    	smsw	%ax
    	bts	$0	,%ax
    	lmsw	%ax

    #	go to 32 code
    	ljmpl	*(APUCode32Vector - APUBootBase)

.code32
.balign 4
APUCode32:
#	go to 64 code

	mov	$0x10,	%ax
	mov	%ax,	%ds
	mov	%ax,	%es
	mov	%ax,	%ss
	mov	%ax,	%fs
	mov	%ax,	%gs

	leal	(APUBootTmpStackEnd - APUBootBase)(%esi),	%eax
	movl	%eax,	%esp

#	open PAE

	movl	%cr4,	%eax
	bts	$5,	%eax
	movl	%eax,	%cr4

#	set page table

	movl	$0x90000,	%eax
	movl	%eax,	%cr3

#	enable long mode

	movl	$0xC0000080,	%ecx
	rdmsr

	bts	$8,	%eax
	wrmsr

#	enable PE & paging

	movl	%cr0,	%eax
	bts	$0,	%eax
	bts	$31,	%eax
	movl	%eax,	%cr0

	ljmp	*(APUCode64Vector - APUBootBase)(%esi)

.code64
.balign 4
APUCode64:
#	go to head.S
	movq	$0x20,	%rax
	movq	%rax,	%ds
	movq	%rax,	%es
	movq	%rax,	%fs
	movq	%rax,	%gs
	movq	%rax,	%ss

    movq	$0x100000,	%rax
	jmpq	*%rax

	hlt


// APU 临时的IDT表
.balign 4
APUTmpIDT:
	.word	0
	.word	0, 0

// APU 临时的GDT表
.balign 4
APUTmpGDT:
	.short	APUTmpGDTEnd - APUTmpGDT - 1
	.long	APUTmpGDT - APUBootBase
	.short	0
	.quad	0x00cf9a000000ffff
	.quad	0x00cf92000000ffff
	.quad	0x0020980000000000
	.quad	0x0000920000000000
APUTmpGDTEnd:

//
.balign 4
APUCode32Vector:
	.long	APUCode32 - APUBootBase
	.word	0x08, 0

.balign 4
APUCode64Vector:
	.long	APUCode64 - APUBootBase
	.word	0x18, 0

.balign 4
APUBootTmpStackStart:
	.org	0x400
APUBootTmpStackEnd:

ENTRY(APUBootEnd)